<template>
  <div>
    <a-radio-group v-if="compType === CompTypeEnum.Radio" v-bind="attrs" v-model:value="state" @change="handleChangeRadio">
      <template v-for="item in dictOptions" :key="`${item.value}`">
        <a-radio :value="item.value">
          {{ item.label }}
        </a-radio>
      </template>
    </a-radio-group>

    <a-radio-group
      v-else-if="compType === CompTypeEnum.RadioButton"
      v-bind="attrs"
      v-model:value="state"
      buttonStyle="solid"
      @change="handleChangeRadio"
    >
      <template v-for="item in dictOptions" :key="`${item.value}`">
        <a-radio-button :value="item.value">
         {{ item.label }}
        </a-radio-button>
      </template>
    </a-radio-group>

    <a-checkbox-group
      v-if="compType === CompTypeEnum.Checkbox"
      v-bind="attrs" v-model:value="state"
      @change="handleCheckboxChange"
    >
      <a-row v-if="colProps && colProps.span">
        <template v-for="item in dictOptions" :key="`${item.value}`">
          <a-col :span="colProps?.span">
            <a-checkbox :value="item.value">{{ item.label }}</a-checkbox>
          </a-col>
        </template>
      </a-row>

      <template v-else v-for="item in dictOptions" :key="`${item.value}`">
        <a-checkbox :value="item.value">{{ item.label }}</a-checkbox>
      </template>
    </a-checkbox-group>

    <template v-else-if="compType === CompTypeEnum.Select">
      <!-- 显示加载效果 -->
      <a-input v-if="loadingEcho" readOnly placeholder="加载中…">
        <template #prefix>
          <LoadingOutlined />
        </template>
      </a-input>
      <a-select
        v-else
        :placeholder="placeholder"
        v-bind="attrs"
        v-model:value="state"
        option-label-prop="label"
        :filterOption="handleFilterOption"
        :getPopupContainer="getPopupContainer"
        @change="handleChange"
      >
        <a-select-option v-if="showChooseOption" :value="null">{{ chooseOptionLabel }}</a-select-option>
        <template v-for="item in dictOptions" :key="`${item.value}`">
          <a-select-option :value="item.value" :label="item.label">
            <span style="display: inline-block; width: 100%" :title="item.label">
              {{ item.label }}
            </span>

            <!-- <span style="display: inline-block; width: 100%" :title="item.label">
              <span>{{ item.label }}</span>
              <a-icon style="float: right; margin-left: 5px;" type="edit" @click.stop=""/>
            </span> -->
          </a-select-option>
        </template>
      </a-select>
    </template>
  </div>

</template>
<script lang="ts">
  import { defineComponent, PropType, ref, reactive, watchEffect, computed, unref, watch, onMounted, nextTick } from "vue"
  import { propTypes } from "/@/utils/propTypes"
  import { useAttrs } from "/@/hooks/core/useAttrs"
  import { initDictOptions } from "/@/utils/dict"
  import { get, omit } from "lodash-es"
  import { useRuleFormItem } from "/@/hooks/component/useFormItem"
  import { CompTypeEnum } from "/@/enums/CompTypeEnum"
  import { LoadingOutlined } from "@ant-design/icons-vue"
  import { isArray } from "/@/utils"

  export default defineComponent({
    name: "JDictSelectTag",
    components: { LoadingOutlined },
    inheritAttrs: false,
    props: {
      value: propTypes.oneOfType([propTypes.string, propTypes.number, propTypes.array, propTypes.bool]),
      dictType: propTypes.string,
      type: propTypes.string,
      colProps: propTypes.object,
      // 如果指定了appId, 目前不会走缓存, 直接用指定的appId调用后端接口
      appId: propTypes.string.def(undefined),
      placeholder: propTypes.string,
      // 默认选择全部
      defaultSelectAll: propTypes.bool,
      stringToNumber: propTypes.bool,
      stringToBool: propTypes.bool,
      // 过滤字典, 为true时, 才展示
      filter: {
        type: Function,
        default: (item) => true,
      },
      valueToString: propTypes.bool.def(true),
      getPopupContainer: {
        type: Function,
        default: (node) => node.parentNode,
      },
      // 是否显示【请选择】选项
      showChooseOption: propTypes.bool.def(true),
      chooseOptionLabel: propTypes.string.def("请选择…"),
      // 下拉项-online使用
      options: {
        type: Array,
        default: [],
        required: false,
      },
    },
    emits: ["options-change", "change", "update:value"],
    setup(props, { emit, refs }) {
      const dictOptions = ref<any[]>([])
      const attrs = useAttrs()
      const [state, formItemContext] = useRuleFormItem(props, "value", "change")
      const getBindValue = Object.assign({}, unref(props), unref(attrs))
      // 是否正在加载回显数据
      const loadingEcho = ref<boolean>(false)
      // 是否是首次加载回显，只有首次加载，才会显示 loading
      let isFirstLoadEcho = true

      //组件类型
      const compType = computed(() => {
        return !props.type || props.type === "list" ? "select" : props.type
      })

      const defaultSelectAll = () => {
        console.log('defaultSelectAll', props.defaultSelectAll)
        let valueLength = 0
        if (isArray(props.value)) {
          valueLength = props.value.length
        }

        if (props.defaultSelectAll && isArray(dictOptions.value) && (!props.value || props.value == '' || valueLength == 0)) {
          console.log('选择全部字段', dictOptions.value)
          const selectValues = dictOptions.value.map((item) => item.value) || []
          emit("change", selectValues)
          emit("update:value", selectValues)
          nextTick(() => formItemContext.onFieldChange())
        }
      }

      /**
       * 监听字典code
       */
      watchEffect(() => {
        if (props.dictType) {
          loadingEcho.value = isFirstLoadEcho
          isFirstLoadEcho = false
          initDictData().finally(() => {
            loadingEcho.value = isFirstLoadEcho
          })
        }
        // 如果没有提供dictType 可以走options的配置--
        if (!props.dictType) {
          dictOptions.value = props.options.filter((e) => props.filter(e.value))
          defaultSelectAll()
        }
      })

      // 使用useRuleFormItem定义的value，会有一个问题，如果不是操作设置的值而是代码设置的控件值而不能触发change事件
      // 此处添加空值的change事件,即当组件调用地代码设置value为''也能触发change事件
      watch(
        () => props.value,
        () => {
          if (props.value === "") {
            emit("change", "")
            emit("update:value", "")
            nextTick(() => formItemContext.onFieldChange())
          }
          defaultSelectAll()
        }
      )

      async function initDictData() {
        let { dictType, stringToNumber, stringToBool, appId } = props
        //根据字典Code, 初始化字典数组
        const dictData = await initDictOptions(dictType, appId)
        dictOptions.value = dictData
          .filter((e) => props.filter(e.value))
          .reduce((prev, next) => {
            if (next) {
              let value = next["value"]
              // value = stringToBool ? value === "true" || value === "1" : value
              prev.push({
                label: next["text"] || next["label"],
                value: stringToNumber ? +value : value,
                ...omit(next, ["text", "value"]),
              })
            }
            return prev
          }, [])
        defaultSelectAll()
      }

      function handleCheckboxChange(value) {
        const { valueToString } = unref<Recordable>(getBindValue)
        state.value = value
        console.log("handleCheckboxChange", state.value, valueToString)

        // 过滤掉空值
        if (state.value == null || state.value === "") {
          state.value = []
        }

        if (Array.isArray(state.value)) {
          state.value = state.value.filter((item) => item != null && item !== "")
        }

        if (Array.isArray(state.value) && valueToString) {
          emit("update:value", state.value.join(","))
        } else  {
          emit("update:value", state.value)
        }
      }

      function handleChange(e) {
        const { mode, valueToString, stringToBool } = unref<Recordable>(getBindValue)
        // 兼容多选模式
        if (mode === "multiple") {
          state.value = e?.target?.value ?? e
        } else {
          state.value = [e?.target?.value ?? e]
        }
        // 过滤掉空值
        if (state.value == null || state.value === "") {
          state.value = []
        } 

        if (Array.isArray(state.value)) {
          state.value = state.value.filter((item) => item != null && item !== "")
        }

        if (Array.isArray(state.value) && valueToString) {
          emit("update:value", state.value.join(","))
        } else  {
          emit("update:value", state.value)
        }
        
        // nextTick(() => formItemContext.onFieldChange());
      }

      /** 单选radio的值变化事件 */
      function handleChangeRadio(e) {
        state.value = e?.target?.value ?? e
        emit("update:value", state.value)
      }

      /** 用于搜索下拉框中的内容 */
      function handleFilterOption(input, option) {
        // 在 label 中搜索
        let labelIf = option.children()[0]?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
        if (labelIf) {
          return true
        }
        // 在 value 中搜索
        return (option.value || "").toString().toLowerCase().indexOf(input.toLowerCase()) >= 0
      }

      return {
        state,
        compType,
        attrs,
        loadingEcho,
        getBindValue,
        dictOptions,
        CompTypeEnum,
        handleChange,
        handleCheckboxChange,
        handleChangeRadio,
        handleFilterOption,
      }
    },
  })
</script>
